package br.cnpq.webflowah.beans;

import java.io.File;
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;

public class WorkflowSemantico implements Serializable {

	private static final long serialVersionUID = 1L;
	
	private List<List<Operacao>> planos = null;
	
	private List<Objetivo> objetivos = new ArrayList<Objetivo>();
		
	private File arquivo = null;
	
	private String uri = null;
	
	private String descricao = null;
	
	private boolean novo = false;
	
	private boolean modificado = false;
	
	private DefaultTreeModel grafo = null;
	
	public WorkflowSemantico() {		
	}
			
	public void addObjetivo(Objetivo objetivo) {
		objetivos.add(objetivo);
		modificado = true;
	}
	
	public void removeObjetivo(Objetivo objetivo) {
		objetivos.remove(objetivo);
		modificado = true;
	}
	
	public List<Objetivo> getObjetivos() {
		return this.objetivos;
	}
		
	public File getArquivo() {
		return this.arquivo;
	}

	public void setArquivo(File arquivo) {
		this.arquivo = arquivo;
		modificado = true;
	}
	
	public String getDescricao() {
		return this.descricao;
	}
	
	public void setDescricao(String descricao) {
		this.descricao = descricao;
		modificado = true;
	}
	
	public void setNovo(boolean flag) {
		this.novo = flag;
	}
		
	public boolean isNovo() {
		return novo;
	}
	
	public void setModificado(boolean flag) {
		this.modificado = flag;
	}
	
	public boolean isModificado() {
		return modificado;
	}

	public String getURI() {
		return uri;
	}

	public void setURI(String uri) {
		this.uri = uri;
	}
	
	public List<URI> getEntradasWorkflow() {
		List<URI> entradas = new ArrayList<URI>();
		for (int i=0; i < objetivos.size(); i++) {
			Objetivo objetivo = objetivos.get(i);
			List list = objetivo.getEntradas();
			for (int j=0; list != null && j < list.size(); j++) {
				Conceito conceito = (Conceito) list.get(j);				
				URI uri = URI.create(conceito.getURI()); 
				entradas.add(uri);
			}
		}
		
		return entradas;		
	}
	
	public List<URI> getEntradas() {
		List<URI> entradas = new ArrayList<URI>();
		List<URI> saidas = new ArrayList<URI>();
		
		for (int i=0; i < objetivos.size(); i++) {
			Objetivo objetivo = objetivos.get(i);
			List list = objetivo.getEntradas();
			for (int j=0; list != null && j < list.size(); j++) {
				Conceito conceito = (Conceito) list.get(j);				
				URI uri = URI.create(conceito.getURI()); 
				entradas.add(uri);
			}
			list = objetivo.getSaidas();
			for (int j=0; list != null && j < list.size(); j++) {
				Conceito conceito = (Conceito) list.get(j);				
				URI uri = URI.create(conceito.getURI());
				saidas.add(uri);
			}
		}
		
		entradas.removeAll(saidas);
		
//		for (int i=0; i < saidas.size(); i++) {
//			entradas.remove(saidas.get(i));
//		}
		
		return entradas;
	}
	
	public List<URI> getPrecondicoes() {
		List<URI> list = new ArrayList<URI>();
		for (int i=0; i < objetivos.size(); i++) {
			Objetivo objetivo = objetivos.get(i);
			List precodicoes = objetivo.getPreCondicoes();
			for (int j=0; precodicoes != null && j < precodicoes.size(); j++) {
				Conceito conceito = (Conceito) precodicoes.get(j);
				URI uri = URI.create(conceito.getURI()); 
				if (list.indexOf(uri) < 0)
					list.add(uri);
			}
		}
		return list;		
	}

	public List<URI> getSaidasWorkflow() {
		List<URI> saidas = new ArrayList<URI>();
		
		for (int i=0; i < objetivos.size(); i++) {
			Objetivo objetivo = objetivos.get(i);
			List list = objetivo.getSaidas();
			for (int j=0; list != null && j < list.size(); j++) {
				Conceito conceito = (Conceito) list.get(j);				
				URI uri = URI.create(conceito.getURI());
				saidas.add(uri);
			}
		}

		return saidas;		
	}

	
	public List<URI> getSaidas() {
		List<URI> entradas = new ArrayList<URI>();
		List<URI> saidas = new ArrayList<URI>();
		
		for (int i=0; i < objetivos.size(); i++) {
			Objetivo objetivo = objetivos.get(i);
			List list = objetivo.getEntradas();
			for (int j=0; list != null && j < list.size(); j++) {
				Conceito conceito = (Conceito) list.get(j);				
				URI uri = URI.create(conceito.getURI()); 
				entradas.add(uri);
			}
			list = objetivo.getSaidas();
			for (int j=0; list != null && j < list.size(); j++) {
				Conceito conceito = (Conceito) list.get(j);				
				URI uri = URI.create(conceito.getURI());
				saidas.add(uri);
			}
		}
		
		for (int i=0; i < entradas.size(); i++) {
			saidas.remove(entradas.get(i));
		}
		
		List<URI> descartes = getDescartes();
		for (int i=0; i < descartes.size(); i++) {
			saidas.remove(descartes.get(i));
		}		

		return saidas;		
//		List<URI> list = new ArrayList<URI>();
//		for (int i=0; i < objetivos.size(); i++) {
//			Objetivo objetivo = objetivos.get(i);
//			List saidas = objetivo.getSaidas();
//			for (int j=0; saidas != null && j < saidas.size(); j++) {
//				Conceito conceito = (Conceito) saidas.get(j);
//				URI uri = URI.create(conceito.getURI()); 
//				if (list.indexOf(uri) < 0)
//					list.add(uri);
//			}
//		}
//		return list;
	}

	public List<URI> getEfeitos() {
		List<URI> list = new ArrayList<URI>();
		for (int i=0; i < objetivos.size(); i++) {
			Objetivo objetivo = objetivos.get(i);
			List efeitos = objetivo.getEfeitos();
			for (int j=0; efeitos != null && j < efeitos.size(); j++) {
				Conceito conceito = (Conceito) efeitos.get(j);
				URI uri = URI.create(conceito.getURI()); 
				if (list.indexOf(uri) < 0)
					list.add(uri);
			}
		}
		return list;
	}
		
	public List<List<Operacao>> getPlanos() {
		return this.planos;
	}
	
	public void setPlanos(List<List<Operacao>> planos) {
		this.planos = planos;
	}

	public void setGrafo(TreeModel grafo) {
		this.grafo = (DefaultTreeModel) grafo;
	}
		
	public TreeModel getGrafo() {
		return this.grafo;
	}
	
	private Set<URI> traverseDescarte(DefaultMutableTreeNode node) {
		Set<URI> set = new HashSet<URI>();
		
		if (node.getUserObject() instanceof Condicao) {
			Set<URI> temp = new HashSet<URI>();
			Condicao condicao = (Condicao) node.getUserObject();
			List expressoes = condicao.getExpressoes();
			for (int i=0; expressoes != null && i < expressoes.size(); i++) {
				Expressao expressao = (Expressao) expressoes.get(i);
				temp.add(URI.create(expressao.getVariavel().getURI()));
			}
			return temp;
		}
		
		for (int i=0; i < node.getChildCount(); i++)
			set.addAll(traverseDescarte((DefaultMutableTreeNode) node.getChildAt(i)));
		
		return set;
	}
	
	public List<URI> getDescartes() {
		List<URI> list = new ArrayList<URI>();
		list.addAll(traverseDescarte((DefaultMutableTreeNode) grafo.getRoot()));
		return list;
	}
	
//	public List<Atividade> getAtividades() {
//		List<Atividade> list = new ArrayList<Atividade>();
//		for (int i=0; i < objetivos.size(); i++) {
//			Objetivo objetivo = objetivos.get(i);
//			Atividade atividade = new Atividade(
//					URI.create(objetivo.getTarefa().getURI()), 
//					URI.create(objetivo.getObjeto().getURI()));
//			list.add(atividade);
//		}
//		return list;		
//	}
	
}
